//  Copyright (c) 2020-present,  INSPUR Co, Ltd.  All rights reserved.
// This source code is licensed under Apache 2.0 License.

// liliupeng@inspur.com
#pragma once

#include <atomic>
#include <list>
#include "pure_mem/abstract_version_node.h"

namespace rocksdb {
// TreeVoidRef object pointer is stored as tree leaf node.
// tree just index user key, no HLC or sequence number.
// TreeVoidRef object contains multi version values for one user key.
class ITreeVoidRef {
public:
  enum struct RefType {
    REFTYPE1,
    REFTYPE2
  };

protected:
  RefType refType_;
public:
  ITreeVoidRef(RefType type) : refType_(type){
    next_.store(nullptr);
    prev_.store(nullptr);
  }
  virtual ~ITreeVoidRef() {}

  virtual ITreeVoidRef *Next() = 0;
  virtual ITreeVoidRef *Prev()  = 0;

  virtual VersionNode *getContentList() = 0;

  virtual bool CASContentList(VersionNode *expected, VersionNode *x) = 0;

  virtual void setContentList(VersionNode *x) = 0;

  virtual void setNext(ITreeVoidRef *x) = 0;

  virtual void setPrev(ITreeVoidRef *x) = 0;

  virtual bool CASNext(ITreeVoidRef *expected, ITreeVoidRef *x) = 0;

  virtual bool CASPrev(ITreeVoidRef *expected, ITreeVoidRef *x) = 0;

  static int CompareTo(ITreeVoidRef *other) {
    // cannot use this function.
    assert(false);
    return 0;
  }

  RefType GetRefType() const {
    return refType_;
  }

private:

  // double link list, store multi version values of current key.
  std::atomic<VersionNode *> version_head_;
  // double link list of TreeVoidRef, each TreeVoidRef node need store prev and
  // next pointer.
  std::atomic<ITreeVoidRef *> prev_;
  std::atomic<ITreeVoidRef *> next_;
};
} // namespace rocksdb